/**
 * Copyright (c) 快宝网络 kuaidihelp.com Co., Ltd. All Rights Reserved 禁止外泄以及用于其它的商业用途
 */

import 'animate.css';
import classNames from 'classnames';
import { isFunction } from 'lodash';
import React, { useEffect, useRef, useState } from 'react';
import './animate.less';
import type {
  AnimateProps,
  AnimateRefCurrent,
  AnimateRounds,
  ChildProps,
  ObserverCSS,
} from './_utils/types';

const AnimateChild: React.FC<AnimateProps> = (props) => {
  const {
    onStart,
    onEnd,
    type,
    children,
    show,
    infinite,
    delay: propsDelay,
    repeat,
    duration,
    reverse,
    elementID,
  } = props;

  const [status, setStatus] = useState('');

  // 开启回退，则暂不支持延迟
  const delay = (!reverse && propsDelay) || 0;
  const style: ObserverCSS = {
    '--animate-duration': duration ? `${duration}s` : null,
    '--animate-delay': delay ? `${delay}s` : null,
    '--animate-repeat': repeat,
  };

  const running = show; // 展示或回退，都指动画运行
  const className = type
    ? classNames('kb-animate animate__animated', {
        [`animate__${type}`]: !!(running && type),
        [`kb-animate__status-${status}`]: !!status,
        'kb-animate__hidden': !running,
        animate__infinite: !!infinite,
        'animate__repeat-1': !!repeat,
        'animate__delay-1s': !!delay,
        'kb-animate__reverse': !!reverse,
      })
    : '';

  // 重复次数 * (动画时长 + 延迟时间)
  const durationTimer = (repeat || 1) * ((duration || 1) + (delay || 0)) * 1000;
  const animateRef = useRef<AnimateRefCurrent>({ count: 0 });

  const triggerStatusChange = (rounds: AnimateRounds) => {
    clearTimeout(animateRef.current.timer);
    if (animateRef.current.show) {
      // 动画开始执行
      setStatus('start');
      if (isFunction(onStart)) {
        onStart({ rounds });
      }
      animateRef.current.timer = setTimeout(() => {
        if (infinite) {
          // 循环播放，不会触发onEnd
          return;
        }
        // 动画执行完毕
        setStatus('end');
        if (isFunction(onEnd)) {
          onEnd({ rounds });
        }
      }, durationTimer);
      animateRef.current.count++;
    }
  };

  useEffect(() => {
    return () => {
      clearTimeout(animateRef.current.timer);
    };
  }, []);

  // 首次动画触发
  useEffect(() => {
    animateRef.current.show = show;
    triggerStatusChange('first');
  }, [show]);

  // next更新动画
  useEffect(() => {
    triggerStatusChange('next');
  }, [type]);

  return (
    <>
      {React.Children.map(children, (child) => {
        if (React.isValidElement(child)) {
          const { type: childType, props: childProps } = child;
          const {
            style: childPropsStyle,
            className: childPropsCls,
            id: childPropsId,
            ...restChildProps
          } = childProps;

          // id为elementID的元素不触发动画效果
          if (elementID && childPropsId === elementID) {
            return child;
          }

          let newChildProps: ChildProps = {
            style: {
              ...childPropsStyle,
              ...style,
            },
            className: classNames(childPropsCls, className),
          };

          if (isFunction(childType) && AnimateChild === childType) {
            // 合并子组件与父组件的属性
            newChildProps = {
              repeat,
              reverse,
              type,
              delay,
              infinite,
              duration,
              ...newChildProps,
              ...restChildProps,
              show,
            };
          }

          return React.cloneElement(child, newChildProps);
        }

        return (
          <span style={style} className={classNames(className, 'kb-animate__span')}>
            {child}
          </span>
        );
      })}
    </>
  );
};

AnimateChild.defaultProps = {
  show: true,
};

export default AnimateChild;
